define(function(require, exports, module) {
    'use strict';
    
    var rk = require('rk');

    
    var rk_userService = require('core/services/2.0/rk_userService');
    
    var scheduleUtil = require('oa/js/schedule/asset/utils/scheduleUtil');
    var g_colorSettings = require('../colorSettings');

    var currentPageUserId = SESSION.user.id;

    (function (){
        $.widget( "rk.fullCalendarPlus", {
            options: {
            },
            eventMap: new Array(),
            currentTasks: [],
            _create: function() {
                var me = this;
                var elem = me.element;
            },
            addTasks: function (task){
                var me = this;
                var elem = me.element;
                var view = $(elem).fullCalendar('getView');
                var viewName = view.name;
                //me.currentTasks = [];
                if($.isArray(task)){
                    for(var i = 0, len = task.length; i < len; i++){
                        var ts = task[i];
                        ts = me._updateAsTask(ts);
                        if(true && viewName == 'month'){
                            ts.title = '<span style="display:none;">'+ts.planFinishDate.valueOf() + '</span>' + ts.title;
                        }
                    }
                    $(elem).fullCalendar('addEventSource', task);
                    me.currentTasks = task;
                }else{
                    task = me._updateAsTask(task);
                    me.currentTasks.push(task);
                    $(elem).fullCalendar('renderEvent', task, true/*stick*/);       
                }            
            },        
            addCalEvent: function (eobj){            
                var me = this;
                var elem = me.element;
                var view = $(elem).fullCalendar('getView');
                var viewName = view.name;
                var second_plus = 0;
                if($.isArray(eobj)){
                    for(var i = 0, len = eobj.length; i < len; i++){
                        //$(elem).fullCalendarPlus('addCalEvent', eobj[i]);
                        eobj[i] = me._updateAsSchedule(eobj[i]);

                        var eo = eobj[i];
                        var sss = moment(eo.start);
                        sss.hours(eo.valueStartMom.hours());
                        sss.minutes(eo.valueStartMom.minutes());
                        sss.seconds(eo.valueStartMom.seconds());

                        var eee = moment(eo.end);
                        eee.hours(eo.valueEndMom.hours());
                        eee.minutes(eo.valueEndMom.minutes());
                        eee.seconds(eo.valueEndMom.seconds());

                        eo.startMS = sss.valueOf();
                        eo.endMS = eee.valueOf();
                    }
                    //TODO: optimize this if{}
                    if(true && viewName == 'month'){
                        eobj = scheduleUtil.sortDayEvents(eobj);//sort by rule: startDate > endDate > id
                        for(var i = 0, len = eobj.length; i < len; i++){
                            var event = eobj[i];
                            event.start.hours(1)
                            event.start.minutes(0)
                            event.start.seconds(0)
                            event.start.add(i, 'seconds')
                            // if(event.isRepeat){
                            //     event.start.hours(1);
                            //     event.start.minutes(0);
                            //     event.start.seconds(0);
                            //     event.start.add(second_plus, 'seconds');                            
                            // }else if(event.valueEndMom.isSame(event.valueStartMom, 'day')){
                            //     event.start.hours(8);
                            //     event.start.minutes(0);
                            //     event.start.seconds(0);
                            //     event.start.add(second_plus, 'seconds');
                            //     event.end = moment(event.start);
                            //     event.end.add(5, 'minutes');
                            // }
                            // //event.title = event.id+'('+(event.isRepeat?'R':'')+')'+moment(event.valueStartMom).format()
                            // event.title = '<span style="display:none;">'+i+'</span>' + event.title;
                            // second_plus++;
                        }
                    }
                    $(elem).fullCalendar( 'addEventSource', eobj );
                }else{
                    eobj = me._updateAsSchedule(eobj);
                    $(elem).fullCalendar('renderEvent', eobj, true/*stick*/);
                }
            },
            _updateAsSchedule: function (eobj){
                var me = this;
                var elem = me.element;
                var view = $(elem).fullCalendar('getView');
                var viewName = view.name;
                eobj.id = eobj.id ? eobj.id : 'e_'+Math.random();
                eobj.ori_title = eobj.title;

                eobj.start = moment(eobj.start);
                eobj.end = moment(eobj.end);

                var sm_value = moment(eobj.valueStartMom);
                var em_value = moment(eobj.valueEndMom);
                var sm_value_minate = sm_value.minutes();
                var em_value_minate = em_value.minutes();

                var sm_value_hours = sm_value.hours();
                var em_value_hours = em_value.hours();

                //DISPLAY:
                if(viewName != 'month'){//mouse will be changed in addCalEvent()
                    //if(eobj.valueEndMom.diff(eobj.valueStartMom, 'days') >= 1){
                    if(!eobj.valueAllDay)
                    if(!eobj.valueEndMom.isSame(eobj.valueStartMom, 'days')){
                        if(viewName == 'agendaDay'){
                            //Rule4.1，日视图下的跨天显示请参考Rule4.1
                            var viewDay = view.start;
                            if(eobj.start.isBefore(viewDay, 'day') && eobj.end.isAfter(viewDay, 'day')){
                                //头尾跨视图当天
                                eobj.allDay =  true;
                                eobj.valueAllDay = true;
                            }else{
                                eobj.allDay =  false;
                                //头或尾未跨视图当天，显示在非全天中
                                var viewDayTime = moment(viewDay);
                                if(eobj.start.isSame(viewDayTime, 'days')){
                                    //跨天日程的首日下半天
                                    eobj.start.hours(sm_value.hours());
                                    eobj.start.minutes(sm_value.minutes());
                                    eobj.start.seconds(sm_value.seconds());
                                    em_value_hours = 23;//文案
                                    em_value_minate = 59;
                                }
                                if(eobj.end.isSame(viewDayTime, 'days')){
                                    //跨天日程的尾日上半天                             
                                    sm_value_hours = 0;//文案
                                    sm_value_minate = 0;
                                    eobj.end.hours(em_value.hours());
                                    eobj.end.minutes(em_value.minutes());
                                    eobj.end.seconds(em_value.seconds());
                                }
                            }
                        }else{
                            eobj.allDay =  true;//Rule4，周视图下跨天显示为全天事件
                        }                        
                    }else
                    if(!eobj.valueAllDay){
                        eobj.allDay = false;
                        eobj.start.hours(sm_value.hours());
                        eobj.start.minutes(sm_value.minutes());
                        eobj.start.seconds(sm_value.seconds());
                        eobj.end.hours(em_value.hours());
                        eobj.end.minutes(em_value.minutes());
                        eobj.end.seconds(em_value.seconds());
                    }else{
                        eobj.allDay = true;
                    }
                    {//better height for reading
                        if(eobj.end.isSame(eobj.start) || eobj.end.diff(eobj.start, 'minutes') <= 30){
                                var diff_minutes = eobj.end.diff(eobj.start,'minutes');
                                var df = 30-diff_minutes;
                                eobj.end.add(df, 'minutes');//do not shorter than 30min when displaying
                        }else 
                        if(eobj.end.isSame(eobj.start) || eobj.end.diff(eobj.start, 'minutes') <= 50){
                                var diff_minutes = eobj.end.diff(eobj.start,'minutes');
                                var df = 50-diff_minutes;
                                eobj.end.add(df, 'minutes');//30min< range <50min, should display more than 50min high for multi-line displaying
                        }
                    }
                }
                if(viewName == 'month'){
                    eobj.allDay =  false;//allDay=false in month view, just for correct cross days visual effect
                }
                // if(eobj.isRepeat){
                //     if(viewName == 'month'){
                //         eobj.allDay =  false;//allDay=false in month view, just for correct cross days visual effect
                //     }
                // }else{
                //     if(viewName == 'month'){
                //         eobj.allDay =  false;//allDay=false in month view, just for correct cross days visual effect
                //     }
                // }
                //注意！该if判断用来兼容fullcalendar的bug，亦即allday中，跨日显示会少一天，因此该处的eobj.allDay必须在所有判断之后
                if(eobj.allDay){
                    //fullcalendar issue, under DAY and WEEK view, if is in allDay displaying, and longer than 1day, fullcalendar will lose 1day length when displaying...
                    if(viewName != 'month' && !eobj.valueEndMom.isSame(eobj.valueStartMom, 'days')) eobj.end.add(1, 'days');
                }

                // Rule1. 月视图,全天事件不显示时间,非全天事件只显示开始时间 
                // Rule2.1 周/日视图 , 半小时内只显示开始时间 :   10:00 干啥
                // Rule2.2 周/日视图 , 半小时以上显示开始时间和结束时间 : 10:00 <回车> 干啥
                // Rule3.  周/日视图 , 跨天的日程,显示在全天时间里, 只显示开始时间，不跨天的，显示在不跨天里
                // Rule4, 起止时间超过1天，为全天事件
                // Rule4.1，起止时间超过1天，如果该日程横跨当前日视图的当天，那么事件渲染成全天事件，如果没有横跨，则渲染成非全天事件。

                var sm_str = (sm_value_hours>9?sm_value_hours:'0'+sm_value_hours) + ':' + (sm_value_minate>9?sm_value_minate:'0'+sm_value_minate);
                var em_str = (em_value_hours>9?em_value_hours:'0'+em_value_hours) + ':' + (em_value_minate>9?em_value_minate:'0'+em_value_minate);

                //TITLE:
                //if(eobj.name != '_private'){
                if(eobj.accessible){
                    var prefix = '';
                    if(eobj.colorType.dummyType == 32 && SESSION.tenantType == 1) {
                        if (eobj.visitRecords && eobj.visitRecords.length > 0) {
                            var isFinish = false;
                            for (var i = 0; i < eobj.visitRecords.length; i++) {
                                var createTime = eobj.visitRecords[i].createTime - 0;
                                var startTime = moment(eobj.start._d.getTime()).hour(0).minutes(0).seconds(0).milliseconds(0).toDate().getTime();
                                var endTime = startTime + 1000 * 60 * 60 * 24;
                                if (createTime > startTime && createTime < endTime) {
                                    prefix += '<span class="visit-status-underway"></span>';
                                    isFinish = true;
                                    break;
                                }
                            }
                            if (!isFinish) {
                                var createTime = new Date().getTime();
                                var startTime = moment(eobj.start._d.getTime()).hour(0).minutes(0).seconds(0).milliseconds(0).toDate().getTime();
                                var endTime = startTime + 1000 * 60 * 60 * 24;
                                if (createTime > endTime) {
                                    prefix += '<span class="visit-status-end"></span>';
                                }
                            }
                        } else {
                            var createTime = new Date().getTime();
                            var startTime = moment(eobj.start._d.getTime()).hour(0).minutes(0).seconds(0).milliseconds(0).toDate().getTime();
                            var endTime = startTime + 1000 * 60 * 60 * 24;
                            if (createTime > endTime) {
                                prefix += '<span class="visit-status-end"></span>';
                            }
                        }
                    }
                    if (eobj.createdBy) {
                        var userId = eobj.createdBy;
                        var userInfo = rk_userService.getUserInfo(userId);
                        if (userInfo && currentPageUserId != userId) {
                            var headImageUrl = userInfo.icon;
                            if (headImageUrl)
                                prefix += '<img class="schedule-headImage" alt="" src="' + headImageUrl + '" ucard="uid=' + userId + '">';
                        }
                    }


                    if(viewName == 'month'){
                        prefix = (!eobj.valueAllDay ? '<span class="start-time">' + sm_str +'</span>-&nbsp;' : '') + prefix;
                        eobj.title = prefix + eobj.title;
                    }else{
                        var diff_minutes = em_value.diff(sm_value, 'minutes');
                        if(eobj.allDay){
                            if(eobj.colorType.dummyType == 32){
                                prefix = '<span style="display:none;">a</span>' + prefix;
                            }else {
                                prefix = (!eobj.valueAllDay/*user defiend!!*/ ? '<span style="display:none;">c</span><span class="start-time">' + sm_str + '</span>-&nbsp;' : '<span style="display:none;">b</span>') + prefix;
                            }
                            eobj.title = prefix + eobj.title;
                        }else{
                            prefix = prefix + '<span class="start-time">' + sm_str + '-&nbsp;</span>';
                            if(diff_minutes <= 30){
                                eobj.title = prefix + eobj.title;
                            }else{
                                eobj.title = prefix + '<span class="end-time">' + em_str + '</span>' + '<br>' + eobj.title;
                            }
                        }
                    }
                }else{
                    eobj.title = (!eobj.valueAllDay ? '<span class="start-time">' + sm_str +'</span>-&nbsp;' : '') + '忙碌';
                }

                eobj.editable = false;
                eobj.durationEditable = false;
                eobj.isSchedule = true;

                eobj.className = 'rk-task-schedule';
                if(eobj.isRepeat){
                    eobj.className = eobj.className + ' isRepeat';
                }
                if(viewName == 'month'){
                    eobj.className = eobj.className + ' inline-display';
                }else
                if(eobj.allDay){
                    eobj.className = eobj.className + ' inline-display';
                }
                eobj.className = eobj.className + (eobj.allDay ? ' allday-displaying' : ' daytime-displaying');
                var colorsetting = 'schedule_default';
                if(eobj.colorSetting){
                    colorsetting = eobj.colorSetting;
                }
                eobj.title = /**'<span style="display:none">a</span>' +**/ eobj.title;
                $.extend(eobj, g_colorSettings[colorsetting]);

                return eobj;
            },
            _updateAsTask: function (task){
                var me = this;
                var elem = this.element;
                var view = $(elem).fullCalendar('getView');
                var viewName = view.name;
                var planFinishTime = $.isNumeric(task.planFinishDate) ? moment(parseInt(task.planFinishDate)): moment(task.planFinishDate);
                task.planFinishDate = moment(planFinishTime);
                var now = moment();
                var isOutOfDate = now.isAfter(task.planFinishDate);
                var currentUserId = currentPageUserId;//global
                var userId = task.createdBy + '';
                var ownerId = task.ownerId + '';
                var userInfo = rk_userService.getUserInfo(userId);
                var ownerInfo = rk_userService.getUserInfo(ownerId);
                var isMine = (currentUserId === ownerId);
                var headImageUrl = false;//false means no display            
                if(!isMine){//must show owner image, unless the owner is myself.
                    if(ownerInfo && ownerInfo.icon){
                        headImageUrl = ownerInfo.icon;
                    }else{
                        headImageUrl = '/img/default_face.png';
                    }
                }
                task.ori_title = task.taskName;            
                var statusCss = '';
                var status = task.status;
                status = $.isNumeric(status) ? parseInt(status) : status;
                var isFinished = (status == 2 ? true : false);
                
                if(isMine){//is my own task
                    statusCss = (isFinished ? 'rk_task_mine_finished' : 'rk_task_mine_processing');
                }else{
                    statusCss = (isFinished ? 'rk_task_joint_finished' : 'rk_task_joint_processing');
                }

                task.title = '<span style="display:none">z</span><span class="'+statusCss+'"></span>'+                            
                                '<span class="rk-task-title '+(isOutOfDate && !isFinished ? 'out-of-date-task':'')+' '+(isFinished ? 'is-finished':'')+'">' + 
                                (headImageUrl !== false ? '<img class="schedule-headImage" alt="" src="'+headImageUrl+'" ucard="uid='+userId+'">' : '') +
                                '<span class="start-time">' + task.planFinishDate.format('HH:mm') +'</span>-&nbsp;'+                            
                                '<span class="">' + task.taskName + '</span></span>';
                task.editable = false;
                task.durationEditable = false;
                if(viewName == 'month'){
                    planFinishTime = planFinishTime.format('YYYY-MM-DD');
                    task.start = planFinishTime + 'T23:59:59';
                    task.end = planFinishTime + 'T23:59:59';
                }else{
                    task.start = moment(planFinishTime);
                    var beginOfDay = moment(planFinishTime.format('YYYY-MM-DD') + 'T00:00:00');//00:00:00
                    var diffms = beginOfDay.diff(task.start);
                    diffms = Math.abs(diffms);

                    if(diffms == 0){
                        task.start.subtract(30, 'minutes');
                        task.end = moment(beginOfDay);
                    }else
                    if(diffms < 30*60*1000 /*half hour*/){
                        task.start = moment(beginOfDay);
                        task.end = moment(beginOfDay);
                        task.end.add(30, 'minutes');
                    }else{
                        var minutes = task.start.minutes();
                        // if(minutes>=0 && minutes <=15){
                        //     task.start.minutes(0);                        
                        // }else if(minutes>=45 && minutes <=59){
                        //     task.start.minutes(0);
                        //     task.start.add(1, 'hours');
                        // }else{
                        //     task.start.minutes(30);
                        // }
                        if(minutes>=0 && minutes <=30){
                            task.start.minutes(30);                        
                        }else{
                            task.start.minutes(0);
                            task.start.add(1, 'hours');
                        }

                        task.start.seconds(0);
                        task.end = moment(task.start);
                        task.start.subtract(30, 'minutes');
                        //task.end = moment(task.planFinishDate);
                    }
                }

                task.className = 'rk-task rk-task-title inline-display';
                task.isTask = true;
                var view = $(elem).fullCalendar('getView');
                task.allDay = false;//(view.name == 'month' ? false : true);//should NOT be allDay in "month" view so that task can always below schedules
                $.extend(task, g_colorSettings.task);
                return task;
            },
            removeTasks: function (){
                var me = this;
                var elem = me.element;
                $(elem).fullCalendar('removeEvents', function (eobj){
                    if(eobj.isTask){
                        return true;
                    }
                })
            },
            removeCalEvent: function (id){

            },
            resetMyHeight: function (){
                var me = this;
                var elem = me.element;
                var view = $(elem).fullCalendar('getView');
                var viewName = view.name;
                if(viewName == 'month'){
                    $(elem).fullCalendar('option', 'contentHeight', null);
                }else{
                    var halfHourHeight = 21;
                    var oneHourHeight = halfHourHeight * 2;
                    var visibleHoursHeight = oneHourHeight*16.5;
                    var alldayObj = $('.fc-agenda-allday');
                    var dividerObj = $('.fc-agenda-divider');
                    var dayObj = $('.fc-agenda-divider').next();
                    $(elem).fullCalendar('option', 'contentHeight', alldayObj.height() + dividerObj.height() + visibleHoursHeight);
                    dayObj.beScroll().beScrollTo(oneHourHeight * 8);;//.scrollTop(oneHourHeight * 8);//at 8:00
                }            
            },
            showTimeline: function(){
                var me = this;
                window.clearInterval(window.timeline_timer);
                //$('#calendar').fullCalendarPlus('showTimeline');
                me._showTimeline();
                window.timeline_timer = window.setInterval(function(){
                    //$('#calendar').fullCalendarPlus('showTimeline');
                    me._showTimeline();
                }, 10000); 
            },
            _showTimeline: function(){
                var me = this;
                var elem = me.element;
                var calendar = $(elem);
                var view = calendar.fullCalendar("getView");
                if(view.name == 'month')return;

                var curTime = new Date();

                var timelineCss = 'rk-timeline';
                var timelineHeight = 11;
                var redSpotRadius = 5;
                var redLineHeight = 1;

                var now = moment();
                var start = view.start;
                var end = view.end;

                start = moment(start.format('YYYY-MM-DD') + 'T00:00:00');

                var parentDiv = $(".fc-agenda-slots:visible").parent();
                var timeline = parentDiv.children("."+timelineCss);

                if(now.isBefore(start) || now.isAfter(end)){
                    $('div.'+timelineCss).hide();
                    return;
                }

                    if (curTime.getHours() == 0 && curTime.getMinutes() <= 5) // Because I am calling this function every 5 minutes
                    {// the day has changed
                        var todayElem = $(".fc-today");
                        todayElem.removeClass("fc-today");
                        todayElem.removeClass("fc-state-highlight");

                        todayElem.next().addClass("fc-today");
                        todayElem.next().addClass("fc-state-highlight");
                    }

                    

                    if (timeline.length == 0) { //if timeline isn't there, add it
                        timeline = $("<div>").addClass(timelineCss);
                        timeline.html('<span class="rk-timeline-spot"></span><span class="rk-timeline-indicator"></span>');
                        parentDiv.prepend(timeline);
                    }

                    var curCalView = calendar.fullCalendar("getView");
                    if (curCalView.visStart < curTime && curCalView.visEnd > curTime) {
                        timeline.show();
                    } else {
                        timeline.hide();
                    }
                    timeline.show();

                    var curSeconds = (curTime.getHours() * 60 * 60) + (curTime.getMinutes() * 60) + curTime.getSeconds();
                    var percentOfDay = curSeconds / 86400; //24 * 60 * 60 = 86400, # of seconds in a day
                    var topLoc = Math.floor(parentDiv.height() * percentOfDay);

                    topLoc = topLoc - (timelineHeight - redLineHeight) / 2;
                    timeline.css("top", topLoc + "px");

                    if (curCalView.name == "agendaWeek") { //week view, don't want the timeline to go the whole way across
                        var dayCol = $(".fc-today:visible");
                        if (dayCol.position() != null) {
                            var left = dayCol.position().left + 1;
                            var width = dayCol.width();
                            timeline.css({
                                left: (left - redSpotRadius-2) + "px",
                                width: (width + redSpotRadius+2) + "px"
                            });
                        }
                    }else if(curCalView.name == 'agendaDay'){
                        var agendaAxisWidth = $('.fc-agenda-axis').outerWidth();
                        var left = timeline.offset().left;
                        timeline.css({
                            left: (agendaAxisWidth - redSpotRadius) + 'px'
                        });
                    }
            }
        });
    })();

    return $;
});